﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DPS.Prototype.PolicyBase;
using DPS.Prototype.Model;
using DPS.Prototype.PolicyBase.Filters;

namespace DPS.Prototype.Policy
{
    public class DefaultProdCompetitor : ProdCompetitorBase
    {

        public DefaultProdCompetitor(ProdLine prodLine)
            : base(prodLine)
        {
            InitWorkOrderFilters();
        }

        protected override SubmitResult CompeteProcess()
        {
            if (!base.CheckIsFullCapacity())
            {
                base.CurrentTobeOccupyCapacity.Clear();
                WorkOrder wo = this.FindWorkOrderToBeProduced();
                if (wo != null)
                {
                    Capacity firstCapacity = null;

                    var matchCapacitys = base.ProdLine.Capacitys.Where(c => c.CapacityStatus != CapacityStatus.Locked && c.CapacityStatus != CapacityStatus.TotalOcuppy && (c.TotalUsage - c.OccupiedUsage - c.TobeOccupyUsage > 0));
                    if (matchCapacitys.Count() == 0)
                        return null;
                    firstCapacity = matchCapacitys.First();

                    //   List<Capacity> tobeOccupyCapacity = new List<Capacity>();
                    base.CurrentTobeOccupyCapacity.Add(firstCapacity);
                    float availableCapacity = firstCapacity.TotalUsage - firstCapacity.OccupiedUsage;

                    Capacity nextCapacity = firstCapacity;
                    while (availableCapacity < wo.OpenOrderQty)
                    {
                        nextCapacity = nextCapacity.Next;
                        if (nextCapacity == null)
                        {
                            //Maybe  find next WO,that Open qty less than total available usage
                            //Or maybe check total available usage before finding the WO
                            return null;
                        }
                        else
                        {
                            float availableUsage = nextCapacity.TotalUsage - nextCapacity.OccupiedUsage;
                            if (availableUsage > 0)
                            {
                                availableCapacity = availableCapacity + (nextCapacity.TotalUsage - nextCapacity.OccupiedUsage);
                                base.CurrentTobeOccupyCapacity.Add(nextCapacity);
                            }
                        }
                    }

                    float qty = wo.OpenOrderQty;
                    foreach (Capacity c in base.CurrentTobeOccupyCapacity)
                    {
                        float occupyQty = Math.Min(c.TotalUsage - c.OccupiedUsage, qty);
                        qty = qty - occupyQty;
                        c.TobeOccupyUsage = occupyQty;
                        if (qty == 0)
                            break;
                    }

                    SubmitResult result = new SubmitResult();
                    result.ProdLine = base.ProdLine;
                    result.WorkOrder = wo;
                    result.StartTime = base.CurrentTobeOccupyCapacity.First().StartTime;
                    result.FinishTime = base.CurrentTobeOccupyCapacity.Last().EndTime;
                    result.ProduceQty = wo.OpenOrderQty;
                    return result;
                }
            }
            return null;
        }

        public override List<WorkOrderFiltersBase> OrderFilters
        {
            get { return this._orderFilters; }
        }

        private List<WorkOrderFiltersBase> _orderFilters;
        private void InitWorkOrderFilters()
        {
            this._orderFilters = new List<WorkOrderFiltersBase>();
            this._orderFilters.Add(new PolicyBase.Filters.WorkOrderFilters.GIDateFilters() { OrderNo = 0, IsOptional = false });
            this._orderFilters.Add(new PolicyBase.Filters.WorkOrderFilters.GIDateFilters() { OrderNo = 1, IsOptional = false });
            this._orderFilters.Add(new PolicyBase.Filters.WorkOrderFilters.ContinuityModelsFilter() { OrderNo = 2, IsOptional = true });

        }
    }
}
 